import json

from django.db import transaction
from rest_framework import serializers

import settings
from social.account.models import User
from social.exceptions import UserAvatarNotRealException
from social.feed.models import Post, Comment, PostLike
from social.notification.models import Notification
from social.user.models import UserPostCount, UserLike
from social.user.serializers import SimpleUserSerializer
from social.utils.serializers import HashidField, TimestampField
from social.utils.shortcut import get_object_or_none


class PostSerializer(serializers.ModelSerializer):
    id = HashidField(model=Post)
    content = serializers.CharField(required=False, allow_null=True, allow_blank=True)
    photos = serializers.CharField()
    user = serializers.SerializerMethodField()
    like_count = serializers.IntegerField(read_only=True)
    comment_count = serializers.IntegerField(read_only=True)
    is_like = serializers.SerializerMethodField()
    created_at = TimestampField(read_only=True)

    def create(self, validated_data):
        # 每日最多3条动态
        with transaction.atomic():
            request = self.context.get('request')
            if not request.user.avatar_real:
                raise UserAvatarNotRealException()
            UserPostCount.update_post_count(request.user)
            validated_data['user'] = request.user
            instance = super(PostSerializer, self).create(validated_data)
            return instance

    def get_user(self, instance):
        data = SimpleUserSerializer(instance.user, context=self.context).data
        request = self.context.get('request')
        if request and request.user:
            data['is_follow'] = UserLike.is_follow(request.user, instance.user)
        return data

    def get_is_like(self, instance):
        return instance.id in self._fetch_user_like_list()

    def _fetch_user_like_list(self):
        like_ids = self.context.get('like_ids')
        if like_ids:
            return like_ids
        request = self.context.get('request')
        if request and request.user:
            like_ids = PostLike.objects.values_list('post_id', flat=True).filter(user=request.user)
            self.context.update({'like_ids': like_ids})
            return like_ids

    def to_representation(self, instance):
        data = super(PostSerializer, self).to_representation(instance)
        ps = json.loads(data['photos'])
        for photo in ps:
            photo['url'] = settings.IMAGE_HOST + photo['url']
        data['photos'] = ps
        return data

    class Meta:
        model = Post
        fields = ('id', 'content', 'photos', 'user', 'like_count', 'comment_count', 'is_like', 'created_at')


class PostCommentSerializer(serializers.ModelSerializer):
    id = HashidField(model=Comment)
    content = serializers.CharField()
    parent_id = HashidField(model=Comment, read_only=False, required=False)
    child = serializers.SerializerMethodField()
    user = serializers.SerializerMethodField()
    created_at = TimestampField(read_only=True)
    reply_user_id = HashidField(model=User, read_only=False, required=False)
    reply_user = serializers.SerializerMethodField(required=False, allow_null=True)

    def create(self, validated_data):
        with transaction.atomic():
            post = self.context.get('post')
            request = self.context.get('request')
            validated_data['user'] = request.user
            validated_data['post'] = post
            post.comment_count += 1
            post.save(update_fields=['comment_count'])
            instance = super(PostCommentSerializer, self).create(validated_data)
            parent_id = validated_data.get('parent_id')
            if parent_id:
                parent = get_object_or_none(Comment, id=parent_id)
                parent.child = instance
                parent.save(update_fields=['child'])
            photos = list(json.loads(post.photos))
            # 回复动态
            reply_user_id = validated_data.get('reply_user_id')
            if reply_user_id:
                Notification.objects.create(from_user=request.user, user_id=reply_user_id, content=f'回复了您的评论',
                                            type=Notification.TYPE_COMMENT,
                                            link=f'{settings.APP_NAME}://post/{post.hid}', thumb=photos[0].get('url'))
            else:
                if post.user.id != request.user.id:
                    Notification.objects.create(user=post.user, from_user=request.user, content='评论了您的动态',
                                                type=Notification.TYPE_COMMENT,
                                                link=f'{settings.APP_NAME}://post/{post.hid}', thumb=photos[0].get('url'))
            return parent if parent_id else instance

    def get_user(self, instance):
        return SimpleUserSerializer(instance.user).data

    def get_reply_user(self, instance):
        if not instance.reply_user:
            return None
        return SimpleUserSerializer(instance.reply_user).data

    def get_child(self, instance):
        if not instance.child:
            return None
        return PostCommentSerializer(instance.child).data

    class Meta:
        model = Comment
        fields = ('id', 'parent_id', 'child', 'content', 'user', 'reply_user_id', 'reply_user', 'created_at')


class PostLikeUserSerializer(serializers.ModelSerializer):
    user = SimpleUserSerializer()

    def to_representation(self, instance):
        data = super(PostLikeUserSerializer, self).to_representation(instance)
        return data['user']

    class Meta:
        model = PostLike
        fields = ('user',)


class PostLikeSerializer(serializers.ModelSerializer):
    post = PostSerializer()

    def to_representation(self, instance):
        data = super(PostLikeSerializer, self).to_representation(instance)
        return data.get('post')

    class Meta:
        model = PostLike
        fields = ('post',)
